import datetime
from typing import List
from fastapi import APIRouter, HTTPException, Query, Request
from models.products import Product, ProductCategory, ProductComment, ProductSpec, ProductSpecOption, ProductTopping
from schemas.product_schemas import ProductCommentReplyRequest, ProductCommentReplyResponse, ProductCommentRequest, \
    ProductSchema, CategorySchema, ProductCategoryDSchema, ProductSpecSchemsa, \
    ProductSpecOptionSchemsa, ProductToppingSchema

router = APIRouter(prefix='/products', tags=['商品模块'])

# 搜索商品
@router.get("/search", response_model=list[ProductCategoryDSchema])
async def search_products(
    keyword: str = Query(None, description="搜索关键词，用于匹配商品名称或描述"),
    category_id: int = Query(None, description="分类ID，用于筛选特定分类下的商品")
):
    """搜索商品，支持关键词和分类筛选"""
    try:
        # 基础查询
        query = Product.all()
        
        # 如果提供了分类ID，添加分类筛选条件
        if category_id is not None:
            # 验证分类是否存在
            category = await ProductCategory.get_or_none(id=category_id)
            if not category:
                raise HTTPException(status_code=400, detail="分类不存在")
            query = query.filter(category_id=category_id)
        
        # 如果提供了关键词，添加名称和描述的模糊匹配
        if keyword is not None and keyword.strip():
            keyword = keyword.strip()
            query = query.filter(
                (Product.name.contains(keyword)) | 
                (Product.description.contains(keyword))
            )
        
        # 预加载关联数据
        products = await query.prefetch_related("category", "specs__options")
        
        # 转换为响应模型
        product_list = []
        for product in products:
            product_schema = ProductCategoryDSchema(
                id=product.id,
                name=product.name,
                price=float(product.price),
                description=product.description,
                category=CategorySchema(
                    id=product.category.id,
                    name=product.category.name,
                    description=product.category.description,
                    parent_id=product.category.parent_id
                ),
                image_url=product.image_url,
                video_url=product.video_url,
                specs=[ProductSpecSchemsa(
                    name=spec.name,
                    product=ProductSchema(
                        id=product.id,
                        name=product.name,
                        price=float(product.price),
                        description=product.description,
                        category=CategorySchema(
                            id=product.category.id,
                            name=product.category.name,
                            description=product.category.description,
                            parent_id=product.category.parent_id
                        ),
                        image_url=product.image_url,
                        video_url=product.video_url
                    )
                ) for spec in await product.specs.all()]
            )
            product_list.append(product_schema)
        
        return product_list
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"搜索商品失败: {str(e)}")

# 热门商品
@router.get("/hot_recommendations", response_model=List[ProductSchema])
async def get_hot_recommendations(limit: int = Query(5, ge=1, le=30)):
    """获取热门推荐商品（按销量排序）"""
    try:
        # 查询销量最高的商品作为热门推荐
        hot_products = await Product.filter(
            is_active=True  # 只查询激活状态的商品
        ).order_by(
            "-sales"  # 按销量降序排列
        ).limit(
            limit
        ).prefetch_related("category")
        
        # 转换为响应模型
        result = []
        for product in hot_products:
            category_schema = CategorySchema(
                id=product.category.id,
                name=product.category.name,
                description=product.category.description,
                parent_id=product.category.parent_id
            ) if product.category else None
            
            result.append(ProductSchema(
                id=product.id,
                name=product.name,
                price=float(product.price),
                description=product.description or "",
                category=category_schema,
                image_url=product.image_url or "",
                video_url=product.video_url or ""
            ))
        
        return result
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取热门推荐失败: {str(e)}")

# 处理多级子分类（树形结构）
async def convert_categories_to_schema(categories):
    """将对象列表转换为列表"""
    result = []
    for category in categories:
        children = await category.children.all()  # 遍历每个分类，获取子分类
        children_schema = await convert_categories_to_schema(children)  # 转换子分类
        category_dict = category.__dict__  # 将对象转换为字典
        category_dict['children'] = children_schema
        category_dict.pop('_state', None)  # 移除不需要的键
        result.append(CategorySchema(**category_dict))
    return result  # 返回转换后的分类列表（含树形结构)


@router.get("/secondary_categories", response_model=list[CategorySchema])
async def get_secondary_categories():
    """获取分类"""
    try:
        # 获取所有分类并预加载子分类关系
        categories = await ProductCategory.filter(parent=None).prefetch_related("children")
        return await convert_categories_to_schema(categories)  # 将对象转换为列表
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"获取分类列表失败: {str(e)}")


@router.get("/product_list", response_model=list[ProductCategoryDSchema])
async def get_product_list():
    """获取商品列表"""
    try:
        # 查询所有的商品，并加载分类和规格数据
        products = await Product.all().prefetch_related("category", "specs__options")
        # 遍历商品
        product_list = []
        for product in products:
            product_schema = ProductCategoryDSchema(
                id=product.id,
                name=product.name,
                price=float(product.price),
                description=product.description,
                category=CategorySchema(
                    id=product.category.id,
                    name=product.category.name,
                    description=product.category.description,
                    parent_id=product.category.parent_id
                ),
                image_url=product.image_url,
                video_url=product.video_url,
                specs=[ProductSpecSchemsa(
                    name=spec.name,
                    product=ProductSchema(
                        id=product.id,
                        name=product.name,
                        price=float(product.price),
                        description=product.description,
                        category=CategorySchema(
                            id=product.category.id,
                            name=product.category.name,
                            description=product.category.description,
                            parent_id=product.category.parent_id
                        ),
                        image_url=product.image_url,
                        video_url=product.video_url
                    )
                ) for spec in await product.specs.all()]
            )
            product_list.append(product_schema)
            # print("product_list", product_list)
        return product_list
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/products_by_category/{category_id}", response_model=list[ProductCategoryDSchema])
async def get_products_by_category(category_id: int) -> list[ProductCategoryDSchema]:
    """根据商品分类id获取商品列表"""
    try:
        # 分类是否存在
        category = await ProductCategory.get_or_none(id=category_id)
        if not category:
            raise HTTPException(status_code=400, detail="分类未找到")
        # 筛选出指定分类下的商品,并预加载关联数据
        products = await Product.filter(category=category).prefetch_related("category", "specs__options")
        # 遍历商品，转换为列表，返回商品列表
        product_list = []
        for product in products:
            product_schema = ProductCategoryDSchema(
                id=product.id,
                name=product.name,
                price=float(product.price),
                description=product.description,
                category=CategorySchema(
                    id=product.category.id,
                    name=product.category.name,
                    description=product.category.description,
                    parent_id=product.category.parent_id
                ),
                image_url=product.image_url,
                video_url=product.video_url,
                specs=[ProductSpecSchemsa(
                    name=spec.name,
                    product=ProductSchema(
                        id=product.id,
                        name=product.name,
                        price=float(product.price),
                        description=product.description,
                        category=CategorySchema(
                            id=product.category.id,
                            name=product.category.name,
                            description=product.category.description,
                            parent_id=product.category.parent_id
                        ),
                        image_url=product.image_url,
                        video_url=product.video_url
                    )
                ) for spec in await product.specs.all()]
            )
            product_list.append(product_schema)
        return product_list
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.get("/product_detail/{product_id}", response_model=ProductCategoryDSchema)
async def get_product_detail(product_id: int) -> ProductCategoryDSchema:
    """根据商品 ID 获取商品详情"""
    try:
        # 获取指定 ID 的商品，加载分类和规格信息
        product = await Product.get_or_none(id=product_id).prefetch_related("category", "specs__options")
        if not product:
            raise HTTPException(status_code=400, detail="商品未找到")
        # 将商品数据转换为列表
        product_schema = ProductCategoryDSchema(
            id=product.id,
            name=product.name,
            price=float(product.price),
            inventory=product.inventory,
            sales=product.sales,
            description=product.description,
            category=CategorySchema(
                id=product.category.id,
                name=product.category.name,
                parent_id=product.category.parent_id
            ),
            image_url=product.image_url,
            video_url=product.video_url,
            specs=[ProductSpecSchemsa(
                name=spec.name,
                product=ProductSchema(
                    id=product.id,
                    name=product.name,
                    price=float(product.price),
                    description=product.description,
                    category=CategorySchema(
                        id=product.category.id,
                        name=product.category.name,
                        description=product.category.description,
                        parent_id=product.category.parent_id
                    ),
                    image_url=product.image_url,
                    video_url=product.video_url
                )
            ) for spec in await product.specs.all()]
        )
        return product_schema
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))


@router.get("/spec_option_list", response_model=List[ProductSpecOptionSchemsa])
async def get_spec_option_list():
    """获取商品规格选项列表"""
    try:
        # 获取所有规格选项，并加载关联的规格和商品信息
        options = await ProductSpecOption.all().prefetch_related(
            "spec",
            "spec__product",
            "spec__product__category"
        )
        # 遍历规格选项，转换为列表格式
        option_list = []
        for option in options:
            # 构建规格选项schema
            option_schema = ProductSpecOptionSchemsa(
                name=option.name,
                spec=ProductSpecSchemsa(
                    name=option.spec.name,
                    product=ProductSchema(
                        id=option.spec.product.id,
                        name=option.spec.product.name,
                        price=float(option.spec.product.price),
                        description=option.spec.product.description,
                        category=CategorySchema(
                            id=option.spec.product.category.id,
                            name=option.spec.product.category.name,
                            description=option.spec.product.category.description,
                            parent_id=option.spec.product.category.parent_id
                        ),
                        image_url=option.spec.product.image_url,
                        video_url=option.spec.product.video_url
                    )
                )
            )
            option_list.append(option_schema)
        # 返回规格选项列表
        return option_list
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"获取规格选项列表失败: {str(e)}")


@router.get("/{product_id}/specs_and_options", response_model=dict)
async def get_product_specs_and_options(product_id: int):
    """根据商品id获取商品规格和选项信息"""
    try:
        # 验证商品是否存在并预加载分类
        product = await Product.get_or_none(id=product_id).prefetch_related("category")
        if not product:
            raise HTTPException(status_code=400, detail="商品不存在")

        # 确保category已加载
        if not hasattr(product, 'category'):
            raise HTTPException(status_code=400, detail="商品分类信息加载失败")

        # 获取该商品的所有规格并预加载选项
        specs = await ProductSpec.filter(
            product_id=product_id,
            is_enabled=True
        ).prefetch_related("options")

        # 获取分类schema（确保是单个对象）
        category_schema = await get_category_schema(product.category)

        # 构建规格列表
        spec_list = []
        option_list = []
        # 遍历规格和选项，构建列表
        for spec in specs:
            # 规格信息
            spec_schema = ProductSpecSchemsa(
                name=spec.name,
                product=ProductSchema(
                    id=product.id,
                    name=product.name,
                    price=float(product.price),
                    description=product.description,
                    category=category_schema,  # 使用预加载的分类schema
                    image_url=product.image_url,
                    video_url=product.video_url
                )
            )
            spec_list.append(spec_schema)

            # 规格选项信息
            options = await spec.options.all()  # 确保获取选项列表
            for option in options:
                option_schema = ProductSpecOptionSchemsa(
                    name=option.name,
                    spec=spec_schema
                )
                option_list.append(option_schema)
        # 返回规格列表和选项列表
        return {
            "status_code": 200,
            "message": "获取商品规格信息成功",
            "specs": spec_list,
            "options": option_list
        }
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"获取商品规格信息失败: {str(e)}")


async def get_category_schema(category: ProductCategory) -> CategorySchema:
    """将分类对象转换为schema"""
    # 确保category是单个对象而不是QuerySet
    if hasattr(category, 'id'):
        return CategorySchema(
            id=category.id,
            name=category.name,
            description=category.description,
            parent_id=category.parent_id
        )
    else:  # 如果是QuerySet，取第一个
        category = await category.first()
        return CategorySchema(
            id=category.id,
            name=category.name,
            description=category.description,
            parent_id=category.parent_id
        )


# 根据商品 ID 获取对应的小料列表
@router.get("/get_toppings/{product_id}", response_model=list[ProductToppingSchema])
async def get_product_toppings(product_id: int):
    """根据商品 ID 获取可用的小料列表"""
    try:
        # 校验商品是否存在
        product = await Product.get_or_none(id=product_id)
        if not product:
            raise HTTPException(status_code=400, detail="商品不存在")

        # 查询该商品下所有启用的小料
        toppings = await ProductTopping.filter(
            product_id=product_id,
            is_enabled=True  # 只返回启用的小料
        ).order_by("name")

        return toppings
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"获取小料列表失败: {str(e)}")


@router.post("/{product_id}/comments", response_model=ProductCommentRequest)
async def add_product_comment(
        product_id: int,
        comment: ProductCommentRequest,
        request: Request
):
    """添加商品评论"""
    try:
        username = request.state.username
        if not username:
            # token 验证失败
            raise HTTPException(status_code=401, detail="用户未登录")
        # 1. 验证商品存在
        product = await Product.get_or_none(id=product_id)
        if not product:
            raise HTTPException(status_code=400, detail="商品未找到")

        # 2. 验证订单存在
        from models.payment import OrderFake
        order = await OrderFake.get_or_none(id=comment.order_id)
        if not order:
            raise HTTPException(status_code=400, detail=f"订单ID {comment.order_id} 不存在")

        # 3. 验证评分范围
        if not (1 <= comment.rating <= 5):
            raise HTTPException(status_code=400, detail="评分必须为1-5星")

        # 4. 创建评论（关联规格选项）
        new_comment = await ProductComment.create(
            product_id=product_id,
            user_id=comment.user_id,
            order_id=comment.order_id,
            rating=comment.rating,
            content=comment.content,
            images=comment.images,
            is_auto=comment.is_auto,
        )
        return new_comment
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"提交评论失败: {str(e)}")


@router.get("/{product_id}/comments", response_model=List[ProductCommentRequest])
async def get_product_comments(product_id: int, request: Request):
    """根据商品ID获取商品评论"""
    try:
        # 验证用户是否登录
        username = request.state.username
        if not username:
            raise HTTPException(status_code=401, detail="用户未登录")

        # 验证商品是否存在
        product = await Product.get_or_none(id=product_id)
        if not product:
            raise HTTPException(status_code=400, detail="商品未找到")

        # 获取该商品的所有评论
        comments = await ProductComment.filter(product_id=product_id).all()
        return comments
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"获取商品评论失败: {str(e)}")


@router.post("/{product_id}/comments/reply", response_model=ProductCommentReplyResponse)
async def reply_to_product_comment(
        product_id: int,
        request_data: ProductCommentReplyRequest,
        request: Request
):
    """回复商品评论（通过商品ID和评论内容）"""
    try:
        username = request.state.username
        if not username:
            raise HTTPException(status_code=401, detail="用户未登录")

        # 1. 验证商品是否存在
        product = await Product.get_or_none(id=product_id)
        print("/////", product)
        if not product:
            raise HTTPException(status_code=400, detail="商品未找到")

        # 2. 通过商品ID和评论内容匹配评论（这里假设通过评论内容精确匹配）
        # 注意：实际应用中可能需要更可靠的匹配方式，如结合用户ID等
        comment = await ProductComment.get_or_none(
            product_id=product_id,
            content=request_data.content
        )
        print('ddd', comment)
        if not comment:
            raise HTTPException(status_code=400, detail="未找到匹配的评论")

        # 3. 保存回复内容
        comment.reply_content = request_data.reply_content
        comment.created_at = datetime.datetime.now()
        await comment.save()

        return {"message": "评论回复成功"}
    except Exception as e:
        raise HTTPException(status_code=400, detail=str(e))
